home *** CD-ROM | disk | FTP | other *** search
/ MacHack 1994 / MacHack 1994.toast / MacHack™94 / Talks & Papers / Michael D. Crawford↵ / Word Services SDK 1.0.5 / Writeswell Jr. Source / Scroll.c < prev    next >
Text File  |  1993-03-17  |  9KB  |  363 lines

  1. /* Scroll.c
  2.  * Handle window scrolling in Writeswell, Jr.
  3.  * ©1992 Working Software, Inc.
  4.  * This source code is copyrighted.  Permission is granted to use the Word Services
  5.  * portion of the Writeswell Jr. source code in your own programs, but you 
  6.  * may not distribute the Writeswell Jr. word-processor code as a 
  7.  * commercial product.  If you modify the code, please do not call it 
  8.  * Writeswell Jr. (or Writeswell.)  This will ensure that people understand the 
  9.  * program and don’t have to deal with a number of different versions with 
  10.  * who-knows-what going on in the code.
  11.  * 
  12.  * Writeswell Jr. and Writeswell are trademarks of Working Software, Inc.
  13.  * 18 Apr 92 Mike Crawford
  14.  */
  15.  
  16. #include <EPPC.h>
  17. #include <AppleEvents.h>
  18. #include <AEObjects.h>
  19. #include "AERegistry.h"
  20. #include "TBConstants.h"
  21. #include "TBGlobals.h"
  22. #include "Scroll.h"
  23.  
  24.  
  25. void DoControl( WindowPtr theWindow, ControlHandle ctlHdl, short partCode, Point where )
  26. {
  27.     short    oldVal;
  28.     short    newVal;
  29.  
  30.     gScrollWindow = theWindow;
  31.  
  32.     switch ( partCode ){
  33.         case inUpButton:
  34.         case inDownButton:
  35.         case inPageUp:
  36.         case inPageDown:
  37.             
  38.             TrackControl( ctlHdl, where, TrackScrollBar );
  39.             break;
  40.         case inThumb:
  41.             oldVal = GetCtlValue( ctlHdl );
  42.             TrackControl( ctlHdl, where, (ProcPtr)NULL );
  43.             newVal = GetCtlValue( ctlHdl );
  44.             
  45.             if ( newVal != oldVal ){
  46.                 ScrollText( oldVal, newVal, ctlHdl );
  47.             }
  48.  
  49.             break;    
  50.     }
  51.  
  52.     return;
  53. }
  54.  
  55. pascal void TrackScrollBar( ControlHandle ctlHdl, short partCode )
  56. {
  57.     short        max;
  58.     short        min;
  59.     short        val;
  60.     short        newVal;
  61.     
  62.     max = GetCtlMax( ctlHdl );
  63.     min = GetCtlMin( ctlHdl );
  64.     val = GetCtlValue( ctlHdl );
  65.     newVal = val;
  66.  
  67.     switch ( partCode ){
  68.         case inUpButton:
  69.             if ( val > min )
  70.                 newVal = val - 1;
  71.             break;
  72.         case inDownButton:
  73.             if ( val < max )
  74.                 newVal = val + 1;
  75.             break;
  76.         case inPageUp:
  77.             newVal = val - gLinesPerPage;
  78.             
  79.             if ( newVal < min )
  80.                 newVal = min;
  81.             break;
  82.  
  83.         case inPageDown:
  84.             newVal = val + gLinesPerPage;
  85.             
  86.             if ( newVal > max )
  87.                 newVal = max;            
  88.             break;
  89.     }
  90.     
  91.     if ( newVal != val ){
  92.         ScrollText( val, newVal, ctlHdl );
  93.     }
  94.  
  95.     return;
  96. }
  97.  
  98. void ScrollText( short oldVal, short newVal, ControlHandle ctlHdl )
  99. {
  100.     TEHandle    textH;
  101.     short        dV;
  102.  
  103.     SetCtlValue( ctlHdl, newVal );
  104.     
  105.     textH = (TEHandle)GetWRefCon( gScrollWindow );
  106.  
  107.     /* 1.0d15 Styled TextEdit requires that we use TEGetHeight to get the height
  108.      * of the actual line, since it is variable.  Under STE, lineHeight is -1.
  109.      *
  110.      * Also, TEGetHeight includes the height of both lines... If we are measuring
  111.      * the height of line 2, we want to do TEGetHeight( 2, 2, textH ).  We need to
  112.      * check for cases of going up and going down.  If we are at the top, though,
  113.      * we want to do TEGetHeight( 0, 1, textH )
  114.      */
  115.     
  116.     if ( newVal > oldVal ){
  117.         /* We're scrolling towards the bottom of the text */
  118.         
  119.         if ( oldVal != 0 ){
  120.             newVal--;
  121.         }
  122.         dV = -TEGetHeight( oldVal, newVal, textH );
  123.     }else{
  124.         /* We're scrolling towards the top of the text */
  125.         /* STUB not sure if I gotta check if we're at the bottom */        
  126.  
  127.         if ( oldVal != 0 ){
  128.             newVal++;
  129.         }
  130.         dV = TEGetHeight( oldVal, newVal, textH );
  131.     }
  132.  
  133. #ifdef NEVER    
  134.     dV = ( oldVal - newVal ) * (*textH)->lineHeight;
  135. #endif
  136.     
  137.     TEScroll( 0, dV, textH );
  138.  
  139.     return;
  140. }
  141.  
  142. Boolean TrackContentClick( void )
  143. {
  144.     Point        where;
  145.     Rect        viewRect;
  146.     TEHandle    textH;
  147.     ControlHandle    ctlHdl;
  148.     GrafPtr            curPort;
  149.     RgnHandle        oldClip;
  150.     Rect            scrollRect;
  151.     Boolean            needRedraw;
  152.     
  153.     /* Track the mouse while it is clicked in the window, and scroll the textEdit
  154.      * field if necessary.  We must always return true.  We have to set the port
  155.      * so that GetMouse will have the right window's local coordinates.
  156.      */
  157.  
  158.     GetPort( &curPort );
  159.     SetPort( gScrollWindow );
  160.  
  161.     GetMouse( &where );
  162.  
  163.     textH = (TEHandle)GetWRefCon( gScrollWindow );
  164.     
  165.     viewRect = (*textH)->viewRect;
  166.     
  167.     ctlHdl = ((WindowPeek)gScrollWindow)->controlList;        /* We know there's 1 control */
  168.  
  169.     needRedraw = false;
  170.  
  171.     /* If the mouse is above or below the window, we fake a mouse click on the scroll bar */
  172.     if ( where.v < viewRect.top ){
  173.         TrackScrollBar( ctlHdl, inUpButton );
  174.         needRedraw = true;
  175.     } else if ( where.v > viewRect.bottom ){
  176.         TrackScrollBar( ctlHdl, inDownButton );
  177.         needRedraw = true;
  178.     }
  179.     
  180.     /* We need to redraw the control so that the user can see the thumb move.
  181.      * This involved setting the clip region to include scroll bar.
  182.      */
  183.  
  184.     if ( needRedraw ){
  185.         oldClip = NewRgn();
  186.         if ( oldClip ){
  187.             GetClip( oldClip );
  188.             scrollRect = (*ctlHdl)->contrlRect;
  189.             ClipRect( &scrollRect );
  190.             Draw1Control( ctlHdl );
  191.             SetClip( oldClip );
  192.             DisposeRgn( oldClip );
  193.         }
  194.     }
  195.  
  196.     SetPort( curPort );
  197.  
  198.     return true;
  199. }
  200.  
  201. void SizeVertScroll()
  202. {
  203.     MoveControl( gVertScroll, thePort->portRect.right - 15, -1 );
  204.     SizeControl( gVertScroll, 16, thePort->portRect.bottom - thePort->portRect.top - 13 );
  205.  
  206.     return;
  207. }
  208.  
  209. void SetVertScroll( WindowPtr theWindow, ControlHandle scrollHdl )
  210. {
  211.     short        totalHeight;
  212.     short        viewHeight;
  213.     TEHandle    hTE;
  214.     Rect        viewRect;
  215.     Rect        destRect;
  216.     short        nLines;
  217.     short        tweenHeight;
  218.     short        i;
  219.     short        scrollAmt;
  220.     short        offSet;
  221.  
  222.     /* The limits of the scroll bar range from 0 to the first line of the last
  223.      * "windowfull" of text.  That is, if there are 50 lines of text, and 10 lines
  224.      * would fit in the window, then the limits are 0 through 40.  If the window is
  225.      * resized so that 20 lines of text would fit, then the limits are 0 and 30.  This
  226.      * way, when the thumb is all the way at the bottom, the last line of text is at
  227.      * the bottom of the window.
  228.      */
  229.  
  230.     hTE = (TEHandle)GetWRefCon( theWindow );
  231.  
  232.     nLines = (*hTE)->nLines;
  233.  
  234.     totalHeight = TEGetHeight( 0, nLines - 1, hTE );
  235.     
  236.     viewRect = (*hTE)->viewRect;
  237.     destRect = (*hTE)->destRect;
  238.  
  239.     viewHeight = viewRect.bottom - viewRect.top;
  240.  
  241.     /* if the last line of text does not fall at or below the bottom of the window,
  242.      * scroll the text down so it does, but not so much that the top line of text is
  243.      * lower than the top of the window.
  244.      */
  245.     
  246.     offSet = viewRect.top - destRect.top;
  247.  
  248.     if ( totalHeight >= viewHeight && ( totalHeight - offSet < viewRect.bottom ) ){
  249.         scrollAmt = -( totalHeight - offSet - viewRect.bottom );
  250.         scrollAmt -= TEGetHeight( nLines, nLines, hTE );
  251.         TEScroll( 0, scrollAmt, hTE );
  252.         viewRect = (*hTE)->viewRect;
  253.         viewHeight = viewRect.bottom - viewRect.top;
  254.         destRect = (*hTE)->destRect;
  255.     }
  256.     
  257.     if ( totalHeight < viewHeight ){
  258.     
  259.         /* All of the text will fit in the window.  Scroll the text so the first
  260.          * line is at the top, and turn off the scroll bar.
  261.          */
  262.         
  263.         scrollAmt = viewRect.top - (*hTE)->destRect.top;
  264.         TEScroll( 0, scrollAmt, hTE );
  265.         
  266.         HiliteControl( scrollHdl, 255 );
  267.     
  268.         return;
  269.     }
  270.     
  271.     /* The text does not all fit.  Find out how many lines from the bottom would fit */
  272.         
  273.     for ( i = nLines - 1; i > 0; i-- ){
  274.         tweenHeight = TEGetHeight( nLines, i, hTE );
  275.         
  276.         if ( tweenHeight >= viewHeight )
  277.             break;
  278.     }
  279.     
  280.     /* i is now the line number of the first line that would be in the window if
  281.      * we had scrolled all the way to the bottom
  282.      */
  283.     
  284.     SetCtlMax( scrollHdl, i - 1 );
  285.  
  286.     /* Save the number of lines on a page for later use by scroll bar tracker */
  287.     
  288.     gLinesPerPage = nLines - i;
  289.  
  290.     for ( i = 1; i < nLines; i++ ){
  291.         tweenHeight = TEGetHeight( 1, i, hTE );
  292.  
  293.         if ( tweenHeight > viewRect.top - destRect.top )
  294.             break;
  295.     }
  296.     
  297.     /* i is now the line number of the first line in the window 
  298.      */
  299.     
  300.     SetCtlValue( scrollHdl, i );
  301.  
  302.     HiliteControl( scrollHdl, 0 );
  303.  
  304.  
  305.     return;
  306. }
  307.  
  308. void ShowSelection( TEHandle hTE )
  309. {
  310.     short    i;
  311.     short    scrollAmt;
  312.     short    linesInRect;
  313.     short    selStart;
  314.     short    viewHeight;
  315.     Rect    viewRect;
  316.     Rect    destRect;
  317.     short    nLines;
  318.     short    lineHeight;
  319.     short    totalHeight;
  320.     short    offset;
  321.     
  322.     selStart = (*hTE)->selStart;
  323.     
  324.     viewRect = (*hTE)->viewRect;
  325.     destRect = (*hTE)->destRect;
  326.     
  327.     offset = viewRect.top - destRect.top;
  328.     
  329.     nLines = (*hTE)->nLines;
  330.     /*totalHeight = TEGetHeight( 0, nLines - 1, hTE );*/
  331.  
  332.     /* scroll as needed to desired line */
  333.     i= 0;
  334.  
  335.     while( i < nLines && (selStart >= ((*hTE)->lineStarts[i])))
  336.         i++;
  337.     
  338.     viewHeight = viewRect.bottom - viewRect.top;
  339.     
  340.     lineHeight = TEGetHeight( 1, i, hTE );
  341.     
  342.     if ( lineHeight - offset > viewRect.bottom ){
  343.     
  344.         scrollAmt = (lineHeight - viewRect.bottom - offset) + viewHeight / 2;
  345.         
  346.         
  347.     }else if ( lineHeight - offset < viewRect.top ){
  348.  
  349.         /* 1.0.3 MDC I didn't have offset here before - it screwed up
  350.          * when you moved off the top with the cursor keys
  351.          */
  352.  
  353.         scrollAmt = -( (viewRect.top + offset - lineHeight ) + viewHeight / 2 );
  354.         
  355.         if ( scrollAmt < -offset )
  356.             scrollAmt = -offset;            /* Limit scrolling so we don't go past top */
  357.     }else
  358.         return;
  359.  
  360.     TEScroll(0,-scrollAmt,hTE);
  361.     
  362.     return;    
  363. }